﻿// MIT License
// 开源地址：https://gitee.com/co1024/AbcMvc
// Copyright (c) 2021-2023 1024
// Abc.Mvc=Furion+EF+SqlSugar+Pear layui admin.

using Nest;

namespace Abc.Utils;

public static class ElasticClientExtension
{
    /// <summary>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="elasticClient"></param>
    /// <param name="indexName"></param>
    /// <param name="numberOfShards">索引应具有的主分片数,默认为5</param>
    /// <param name="numberOfReplicas">每个主分片具有的副本数。默认为1。</param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public static async Task CreateIndexAsync<T>(this ElasticClient elasticClient, string indexName = "",
        int numberOfShards = 5, int numberOfReplicas = 1) where T : class
    {
        //if (string.IsNullOrWhiteSpace(indexName)) throw new ArgumentException("索引名称不可为空");

        indexName = GetIndexName<T>(indexName);
        ////判断索引是否存在
        //if (!(await elasticClient.Indices.ExistsAsync(indexName)).Exists)
        //{
        var indexState = GetIndexState(indexName, numberOfShards, numberOfReplicas);
        var response =
            await elasticClient.Indices.CreateAsync(indexName,
                p => p.InitializeUsing(indexState).Map<T>(x => x.AutoMap()));
        if (!response.IsValid)
            //失败
            throw new Exception($"创建索引失败:{response.OriginalException.Message}");
        //}
    }

    /// <summary>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="elasticClient"></param>
    /// <param name="indexName"></param>
    /// <param name="numberOfShards">索引应具有的主分片数,默认为5</param>
    /// <param name="numberOfReplicas">每个主分片具有的副本数。默认为1。</param>
    /// <exception cref="Exception"></exception>
    public static void CreateIndex<T>(this ElasticClient elasticClient, string indexName = "", int numberOfShards = 5,
        int numberOfReplicas = 1) where T : class
    {
        //if (string.IsNullOrWhiteSpace(indexName)) throw new ArgumentException("索引名称不可为空");
        indexName = GetIndexName<T>(indexName);
        ////判断索引是否存在
        //if (!elasticClient.Indices.Exists(indexName).Exists)
        //{
        var indexState = GetIndexState(indexName, numberOfShards, numberOfReplicas);
        var response =
            elasticClient.Indices.Create(indexName, p => p.InitializeUsing(indexState).Map<T>(x => x.AutoMap()));
        if (!response.IsValid)
            throw new Exception($"创建索引失败:{response.OriginalException.Message}");
        //}
    }

    /// <summary>
    ///     获取索引状态
    /// </summary>
    /// <param name="indexName"></param>
    /// <param name="numberOfShards">索引应具有的主分片数,默认为5</param>
    /// <param name="numberOfReplicas">每个主分片具有的副本数。默认为1。</param>
    /// <returns></returns>
    private static IndexState GetIndexState(string indexName = "", int numberOfShards = 5, int numberOfReplicas = 1)
    {
        var indexState = new IndexState
        {
            Settings = new IndexSettings
            {
                NumberOfReplicas = numberOfReplicas, //每个主分片具有的副本数。默认为1。
                NumberOfShards = numberOfShards //索引应具有的主分片数,默认为5

                // index.blocks.read_only：设为true,则索引以及索引的元数据只可读
                // index.blocks.read_only_allow_delete：设为true，只读时允许删除。
                // index.blocks.read：设为true，则不可读。
                // index.blocks.write：设为true，则不可写。
                // index.blocks.metadata：设为true，则索引元数据不可读写
            }
        };

        return indexState;
    }

    /// <summary>
    ///     获取索引名
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="indexName"></param>
    /// <returns></returns>
    private static string GetIndexName<T>(string indexName = "") where T : class
    {
        if (string.IsNullOrWhiteSpace(indexName)) indexName = indexName.GetIndex<T>().ToLower();
        return indexName.ToLower();
    }
}